package com.qcby.llmtchstd.websocket;


import com.qcby.llmtchstd.entity.Message;
import com.qcby.llmtchstd.entity.User;
import com.qcby.llmtchstd.service.UserChatService;
import com.qcby.llmtchstd.utils.GsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.util.HtmlUtils;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.Map.Entry;

@Component("chatWebSocketHandler")
public class ChatWebSocketHandler implements WebSocketHandler {
    public static final Map<String, WebSocketSession> USER_SOCKETSESSION_MAP;
    @Autowired
    private UserChatService userChatService;
    static {
        USER_SOCKETSESSION_MAP = new HashMap<String, WebSocketSession>();
    }
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        User loginUser = (User) webSocketSession.getAttributes().get("loginUser");
        // 存储时使用 type:id 作为唯一标识
        String uniqueKey = loginUser.getType() + ":" + loginUser.getId();
        USER_SOCKETSESSION_MAP.put(uniqueKey, webSocketSession);
        System.out.println("webSocketSession:   "+webSocketSession);
        Message msg = new Message();
        msg.setContent(loginUser.getName()+"来啦！");
        msg.setSendTime(LocalDateTime.now());
        Set<Entry<String,WebSocketSession>> entrySet = USER_SOCKETSESSION_MAP.entrySet();
        for(Entry<String,WebSocketSession> entry : entrySet){
            msg.getUserList().add((User)entry.getValue().getAttributes().get("loginUser"));
        }
        System.out.println("msg: "+msg.getUserList());
        TextMessage message = new TextMessage(GsonUtils.toJson(msg));
        System.out.println("message: "+ GsonUtils.toJson(msg) );
        sendMessageToAll(message);
    }

    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> message) throws Exception {
        User loginUser = (User) webSocketSession.getAttributes().get("loginUser");
        if(message.getPayloadLength() == 0) return;
        Message msg = GsonUtils.fromJson(message.getPayload().toString(), Message.class);
        System.out.println("this-----------"+msg.toString());
        msg.setSenderName(loginUser.getName());
        msg.setSendTime(LocalDateTime.now());
        String text = msg.getContent();
        String htmlEscapeText = HtmlUtils.htmlEscape(text);
        msg.setContent(htmlEscapeText);
        msg.setReceiverType("group");
        Integer type = loginUser.getType();
        if(type == 0){
            msg.setSenderType("student");
        }else{
            msg.setSenderType("teacher");
        }

        Integer saveResult = userChatService.chatSave(msg);
        Set<Entry<String,WebSocketSession>> entrySet = USER_SOCKETSESSION_MAP.entrySet();
        for(Entry<String,WebSocketSession> entry : entrySet){
            msg.getUserList().add((User)entry.getValue().getAttributes().get("loginUser"));
        }
        if(msg.getReceiverId()==null||msg.getReceiverType().equals("group")){
            sendMessageToAll(new TextMessage(GsonUtils.toJson(msg)));
        }else{
            //私聊
        }
        msg.setSenderName(null);
        if (saveResult != null) {
            System.out.println("消息已存入数据库，ID: " + saveResult);
        } else {
            System.err.println("消息保存失败");
        }
    }

    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
        System.out.println("Websocket异常断开:" + webSocketSession.getId() + "已经关闭");
        if(webSocketSession.isOpen()){
            webSocketSession.close();
        }

        Message msg = new Message();
        msg.setSendTime(LocalDateTime.now());
        User loginUser = (User)webSocketSession.getAttributes().get("loginUser");
        // 生成与存储时一致的唯一标识
        String uniqueKey = loginUser.getType() + ":" + loginUser.getId();
        // 直接根据唯一标识移除
        if (USER_SOCKETSESSION_MAP.containsKey(uniqueKey)) {
            msg.setContent(loginUser.getName()+"走啦！");
            USER_SOCKETSESSION_MAP.remove(uniqueKey);
            System.out.println("Socket会话已经移除:用户唯一标识" + uniqueKey);
        }
        // 重新构建在线用户列表
        msg.getUserList().clear();
        for(Entry<String,WebSocketSession> entry : USER_SOCKETSESSION_MAP.entrySet()){
            msg.getUserList().add((User)entry.getValue().getAttributes().get("loginUser"));
        }
        TextMessage message = new TextMessage(GsonUtils.toJson(msg));
        sendMessageToAll(message);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        System.out.println("Websocket正常断开:" + webSocketSession.getId() + "已经关闭");
        Message msg = new Message();
        msg.setSendTime(LocalDateTime.now());

        User loginUser=(User)webSocketSession.getAttributes().get("loginUser");
        // 生成与存储时一致的唯一标识
        String uniqueKey = loginUser.getType() + ":" + loginUser.getId();
        // 直接根据唯一标识移除
        if (USER_SOCKETSESSION_MAP.containsKey(uniqueKey)) {
            msg.setContent(loginUser.getName()+"走啦！");
            USER_SOCKETSESSION_MAP.remove(uniqueKey);
            System.out.println("Socket会话已经移除:用户唯一标识" + uniqueKey);
        }
        // 重新构建在线用户列表
        msg.getUserList().clear();
        for(Entry<String, WebSocketSession> entry : USER_SOCKETSESSION_MAP.entrySet()) {
            msg.getUserList().add((User)entry.getValue().getAttributes().get("loginUser"));
        }

        TextMessage message = new TextMessage(GsonUtils.toJson(msg));
        sendMessageToAll(message);
    }


    @Override
    public boolean supportsPartialMessages() {
        return false;
    }


    private void sendMessageToAll(final TextMessage message) {
        Set<Entry<String, WebSocketSession>> entrySet = USER_SOCKETSESSION_MAP.entrySet();
        for (Entry<String, WebSocketSession> entry : entrySet) {
            final WebSocketSession webSocketSession = entry.getValue();
            if(webSocketSession.isOpen()){
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            if (webSocketSession.isOpen()) {
                                webSocketSession.sendMessage(message);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
    }
}